package com.gome.axwl.aoc.standalone.config;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.gome.commons.json.util.JsonUtil;

/***
 * 实现Web层的日志切面
 * 
 * @author WangLongyu 2017年11月15日
 */
@Aspect
@Component
@Order(-5)
public class WebLogAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private ThreadLocal<String> requestMap = new ThreadLocal<>();
    private ThreadLocal<Long> requestTimeMap = new ThreadLocal<>();
    /**
     * 定义一个切入点. 解释下：
     *
     * ~第一个 * 代表任意修饰符及任意返回值. ~第二个 * 任意包名 ~第三个 * 代表任意方法. ~第四个 * 定义在web包或者子包 ~第五个
     * * 任意方法 ~ ..匹配任意数量的参数.
     */
    @Pointcut("execution(public * com.gome.axwl.aoc.web.controller..*.*(..))")
    public void webLog() {
    }

    @Around("webLog()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        requestTimeMap.set(System.currentTimeMillis());
        String requestId = UUID.randomUUID().toString();
        requestMap.set(requestId);
        Map<String, Object> param = new HashMap<>();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String method = point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            if (request != null) {
                for (Enumeration<String> enu = request.getParameterNames(); enu.hasMoreElements();) {
                    String paraName = enu.nextElement();
                    param.put(paraName, request.getParameter(paraName));
                }
            }
        }
        logger.debug("requestId:[{}] method:[{}] param:[{}]", requestId, method, param);
        Object result = null;
        try {
            result = point.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        logger.debug("requestId:[{}] method:[{}] param:[{}] 耗时:[{} ms] 返回结果: {}", requestMap.get(), method,
                param, System.currentTimeMillis() - requestTimeMap.get(),
                result != null ? JsonUtil.toJson(result) : "null", requestMap.get());
        requestMap.remove();
        requestTimeMap.remove();
        return result;
    }

}
